package com.campus.backend.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.campus.common.bean.common.Resp;
import com.campus.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@RestController
@ControllerAdvice
public class ExceptionController {
	@Autowired
	private ObjectMapper objectMapper;
	
	@ExceptionHandler(Exception.class)
	public Resp<?> exceptionDefault(Exception e) {
		log.error(e.getMessage(), e);
		if (e instanceof BusinessException) {
			BusinessException businessException = (BusinessException)e;
			return Resp.error(String.valueOf(businessException.getCode()), businessException.getMessage(), businessException.getContent());
		}
		return Resp.error(e.getMessage());
	}

	/**
	 * 处理 form data方式调用接口校验失败抛出的异常
	 * @param e
	 * @return
	 * @throws JsonProcessingException
	 */
	@ExceptionHandler(BindException.class)
	public Resp<?> bindExceptionHandler(BindException e) throws JsonProcessingException {
		List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
		List<String> collect = fieldErrors.stream()
				.map(FieldError::getDefaultMessage)
				.collect(Collectors.toList());
		return Resp.error(objectMapper.writeValueAsString(collect));
	}

	/**
	 * 处理 json 请求体调用接口校验失败抛出的异常
	 * @param e
	 * @return
	 * @throws JsonProcessingException
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public Resp<?> methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) throws JsonProcessingException {
		List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
		List<String> collect = fieldErrors.stream()
				.map(FieldError::getDefaultMessage)
				.collect(Collectors.toList());
		return Resp.error(objectMapper.writeValueAsString(collect));
	}

	/**
	 * 处理单个参数校验失败抛出的异常
	 * @param e
	 * @return
	 * @throws JsonProcessingException
	 */
	@ExceptionHandler(ConstraintViolationException.class)
	public Resp<?> constraintViolationExceptionHandler(ConstraintViolationException e) throws JsonProcessingException {
		Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
		List<String> collect = constraintViolations.stream()
				.map(ConstraintViolation::getMessage)
				.collect(Collectors.toList());
		return Resp.error(objectMapper.writeValueAsString(collect));
	}

}
